package POJO;

/**
 *
 * @author Sibrand
 */
import java.io.IOException;
import java.io.StringBufferInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Foaf {

    private User u = null;
    private String[] friendIds = null;
    private String[] familyIds = null;
    private String foaf = "";

    public Foaf(User u) {
        this.u = u;
        u.GetInfo();

        friendIds = u.friends;
        familyIds = u.family;
        parseUserToFoaf();
    }

    public String getString() {
        return foaf;
    }

    public String getStringForHtml() {
        String result = foaf.replaceAll("\n", "<br />");
        result = result.replaceAll("\t", "&nbsp;&nbsp;&nbsp;");

        return result;
    }

    private void parseUserToFoaf() {
        if (u != null && u.username != null) {
            foaf += "<rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n" +
                    "xmlns:rdfs=\"http://www.w3.org/2000/01/rdf-schema#\"\n" +
                    "xmlns:foaf=\"http://xmlns.com/foaf/0.1/\"\n" +
                    "xmlns:admin=\"http://webns.net/mvcb/\">\n" +
                    "<foaf:Person rdf:ID=\"me\">\n";

            parseUser();

            foaf += "\t<foaf:knows>\n";

            parseFriends();

            foaf += "\t</foaf:knows>\n</foaf:Person></rdf:RDF>\n";
        }
    }

    private void parseUser() {
        String first = u.fullName.substring(0, u.fullName.indexOf(' '));
        String last = u.fullName.substring(u.fullName.indexOf(' ') + 1, u.fullName.length());

        foaf += "\t<foaf:name>" + u.fullName + "</foaf:name>\n" +
                "\t<foaf:givenname>" + first + "</foaf:givenname>\n" +
                "\t<foaf:family_name>" + last + "</foaf:family_name>\n" +
                "\t<foaf:nick>" + u.username + "</foaf:nick>\n" +
                "\t<foaf:mbox>" + u.email + "</foaf:mbox>\n";
    }

    private void parseFriends() {
        for (int i = 0; i < friendIds.length; ++i) {
            foaf += "\t\t<foaf:Person><foaf:nick>" + friendIds[i] + "</foaf:nick></foaf:Person>\n";
        }

        for (int i = 0; i < familyIds.length; ++i) {
            foaf += "\t\t<foaf:Person><foaf:nick>" + familyIds[i] + "</foaf:nick></foaf:Person>\n";
        }
    }

    public static String[] getFriends(String foaf) throws SAXException, IOException, ParserConfigurationException {
        String jaxpPropertyName = "javax.xml.parsers.DocumentBuilderFactory";
        if (System.getProperty(jaxpPropertyName) == null) {
            String apacheXercesPropertyValue = "org.apache.xerces.jaxp.DocumentBuilderFactoryImpl";
            System.setProperty(jaxpPropertyName, apacheXercesPropertyValue);
        }

        DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = builderFactory.newDocumentBuilder();
        Document document = builder.parse(new StringBufferInputStream(foaf));
        document.getDocumentElement().normalize();
        Element rootElement = document.getDocumentElement();
        rootElement.normalize();

        NodeList friends = rootElement.getElementsByTagName("foaf:nick");

        String[] result = new String[0];
        for (int i = 1; i < friends.getLength(); ++i) { //beginnen bij 1, uw eigen nick moet ge niet meetellen

            result = addTo(result, new String[]{friends.item(i).getTextContent()});
        }

        for (int i = 0; i < result.length; ++i) {
            System.out.println(result[i]);
        }
        return result;
    }
//depth == 1 --> friends worden gevonden, maar die mogen weggelaten worden
    public String[] getFriendsOfFriends(int depth) throws SAXException, IOException, ParserConfigurationException {
        if (depth > 0) {
            String[] friends = getFriends(foaf);
            String[] temp = friends;
            String[] processed = new String[0];

            for (int i = 0; i < depth; ++i) {
                String[] temp2 = new String[0];
                boolean flag = false;
                for (int j = 0; j < temp.length; ++j) {
                    if (!contains(processed, temp[i])) {
                        flag = true;
                        processed = addTo(processed, new String[]{temp[i]});
                        User tempu = new User();
                        tempu.username = temp[i];
                        tempu.GetInfo();
                        Foaf f = new Foaf(tempu);
                        temp2 = addTo(temp2, getFriends(f.getString()));
                    }
                }
                if (flag) {
                    temp = addTo(temp, temp2);
                    temp = removeCopies(temp);
                }
            }

            temp = removeOut(temp, friends);
            return removeOut(temp, new String[]{u.username});
        } else {
            return new String[0];
        }

    }

    private static boolean contains(String[] a, String s) {
        for (int i = 0; i < a.length; ++i) {
            if (a[i].compareTo(s) == 0) {
                return true;
            }
        }
        return false;
    }

    private static String[] removeCopies(String[] foafs) {
        if (foafs.length > 0) {
            String[] result = new String[]{foafs[0]};
            for (int i = 1; i <
                    foafs.length; ++i) {
                if (foafs[i] != null) {
                    boolean found = false;
                    for (int j = 0; j <
                            result.length; ++j) {
                        if (result[j].compareTo(foafs[i]) == 0) {
                            found = true;
                        }

                    }
                    if (!found) {
                        String[] temp = new String[result.length + 1];
                        System.arraycopy(result, 0, temp, 0, result.length);
                        result =
                                temp;
                        result[result.length - 1] = foafs[i];
                    }

                }
            }
            return result;
        } else {
            return new String[0];
        }

    }

    private static String[] addTo(String[] s1, String[] s2) {
        String[] temp = new String[s1.length + s2.length];
        System.arraycopy(s1, 0, temp, 0, s1.length);
        System.arraycopy(s2, 0, temp, s1.length, s2.length);

        return temp;
    }

    private static String[] removeOut(String[] s1, String[] s2) {
        String[] result = new String[0];
        for (int i = 0; i < s1.length; ++i) {
            if (s1[i] != null) {
                boolean found = false;
                for (int j = 0; j < s2.length; ++j) {
                    if (s2[j] != null && s1[i].compareTo(s2[j]) == 0) {
                        found = true;
                    }
                }

                if (!found) {
                    result = addTo(result, new String[]{s1[i]});
                }

            }
        }

        return result;
    }
}
